package com.googlecode.gaal.data.impl;

import com.googlecode.gaal.data.api.IntSequence;

public class ArraySequence extends AbstractSequence {
    protected final int[] array;
    protected final int start;
    protected final int end;

    public ArraySequence(int[] array) {
        this(array, 0, array.length);
    }

    public ArraySequence(int[] array, int start, int end) {
        this.array = array;
        this.start = start;
        this.end = end - 1;
    }

    @Override
    public int get(int index, int defaultValue) {
        if (index < 0 || index >= size())
            return defaultValue;
        else
            return array[start + index];
    }

    @Override
    public int get(int index) throws IndexOutOfBoundsException {
        if (index < 0 || index >= size())
            throw new IndexOutOfBoundsException("" + index);
        else
            return array[start + index];
    }

    @Override
    public IntSequence subSequence(int start, int end) throws IndexOutOfBoundsException {
        if (start < 0 || end > size() || end < start) {
            throw new IndexOutOfBoundsException(start + "-" + end);
        }
        return new ArraySequence(array, this.start + start, this.start + end);
    }

    @Override
    public IntSequence reverse() {
        return new ReverseArraySequence();
    }

    @Override
    public int size() {
        return end - start + 1;
    }

    protected class ReverseArraySequence extends AbstractSequence {
        @Override
        public int get(int index, int defaultValue) {
            if (index < 0 || index >= size())
                return defaultValue;
            else
                return array[end - index];
        }

        public int arrayIndexOf(int index) {
            return end - index;
        }

        @Override
        public int get(int index) throws IndexOutOfBoundsException {
            if (index < 0 || index >= size())
                throw new IndexOutOfBoundsException("" + index);
            else
                return array[end - index];
        }

        @Override
        public IntSequence subSequence(int start, int end) throws IndexOutOfBoundsException {
            if (start < 0 || end > size() || end < start) {
                throw new IndexOutOfBoundsException(start + "-" + end);
            }
            return new ArraySequence(array, (ArraySequence.this.end + 1) - end, (ArraySequence.this.end + 1) - start)
                    .reverse();
        }

        @Override
        public int size() {
            return end - start + 1;
        }

        @Override
        public IntSequence reverse() {
            return ArraySequence.this;
        }

    }
}
